package com.example.taluo.security;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/*** @Author supersaiya
 * @Description 自定义 token生成检验类

 * @Date 2025/2/12 17:16

 * @Version 1.0*/
@Component
public class TokenProvider {
    private static final String SECRET_KEY = "vB2Dsau3RlKAlBSshIQeAWSRKNsP5aBJaMjJ9PkuURA="; // 用于签名的密钥
    private static final String HMAC_ALGORITHM = "HmacSHA256"; // 使用HMAC-SHA256算法 进行签名
    private static final long EXPIRATION_TIME = 3600000; // Token有效期：1小时（毫秒）

    // 生成Token
    public String generateToken(String userId) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        Date exp = new Date(nowMillis + EXPIRATION_TIME);

        Map<String, Object> payload = new HashMap<>();
        payload.put("userId", userId);
        payload.put("iat", now.getTime()); // 签发时间
        payload.put("exp", exp.getTime()); // 过期时间

        //token 头部 使用什么算法
        String header = Base64.getUrlEncoder().withoutPadding().encodeToString("{\"alg\":\"HS256\",\"typ\":\"JWT\"}".getBytes(StandardCharsets.UTF_8));
        //token payload部分 存储id + 有效时间
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonPayload;
        try {
            jsonPayload = objectMapper.writeValueAsString(payload);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to serialize payload", e);
        }
        String payloadStr = Base64.getUrlEncoder().withoutPadding().encodeToString(jsonPayload.getBytes(StandardCharsets.UTF_8));

        String token = header + "." + payloadStr;
        String signature = sign(token, SECRET_KEY);

        return token + "." + signature;
    }

    // 验证Token
    public boolean validateToken(String token) {
        try {
            String[] parts = token.split("\\.");
            if (parts.length != 3) {
                return false;
            }

            String header = parts[0];
            String payload = parts[1];
            String signature = parts[2];

            String tokenToSign = header + "." + payload;
            String expectedSignature = sign(tokenToSign, SECRET_KEY);

            return expectedSignature.equals(signature);
        } catch (Exception e) {
            return false;
        }
    }

    // 从Token中获取用户ID

    public String getUserIdFromToken(String token) {
        try {
            String[] parts = token.split("\\.");
            if (parts.length != 3) {
                return null;
            }

            // 解码 payload 部分
            String payload = new String(Base64.getUrlDecoder().decode(parts[1]), StandardCharsets.UTF_8);

            // 使用 Jackson 将 payload 解析为 Map
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> payloadMap = objectMapper.readValue(payload, Map.class);

            // 提取 userId
            return (String) payloadMap.get("userId");
        } catch (Exception e) {
            e.printStackTrace(); // 打印异常信息以便调试
            return null;
        }
    }

    // 签名方法
    private String sign(String data, String secret) {
        try {
            Key key = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM);
            Mac mac = Mac.getInstance(HMAC_ALGORITHM);
            mac.init(key);
            byte[] rawHmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getUrlEncoder().withoutPadding().encodeToString(rawHmac);
        } catch (Exception e) {
            throw new RuntimeException("Failed to sign data", e);
        }
    }
}